// Copyright 2011 Google Inc. All Rights Reserved.

/**
 * @fileoverview This is the root module for the net-score project.
 * @author gavaletz@google.com (Eric Gavaletz)
 */


goog.provide('netscore');


goog.require('datastore');
goog.require('form');
goog.require('goog.dom');
goog.require('late');
goog.require('page');
goog.require('results');
goog.require('thr');
goog.require('track');
goog.require('yt');


/**
 * This lists all the tests that should be done.
 *
 * Each item in the list should provide a function called start() that takes no
 * arguments and have a variable called nextFunction that can be assigned a
 * function that takes no arguments.
 *
 * @type {Array.<function()>}
 */
netscore.workList = [form, late, thr, yt];


/**
 * Indicates to callback functions is all of the work listed in
 * netscore.workList has been completed.
 *
 * @type {boolean}
 */
netscore.workDone = false;


/**
 * Indicates to callback functions that all of the tests have been setup and are
 * ready to begin.
 *
 * @type {boolean}
 */
netscore.workReady = false;


/**
 * Indicates that the visualization libraries have been loaded and that their
 * dependencies can start.
 *
 * @type {boolean}
 */
netscore.visReady = false;


/**
 * The position in the worklist.
 * @type {number}
 */
netscore.workIndex = 0;


/**
 * The function to be called when the functionis set in the netscore.workList
 * is completed.
 *
 * @type {function()}
 */
netscore.nextFunction;


/**
 * http://code.google.com/apis/loader/
 *
 * This is some tricky stuff and the google.load is not well documented and does
 * some strange things if you are not careful.  Always list the callback
 * function in optional parameters.  See this message for an explination:
 *
 * http://groups.google.com/group/google-maps-api/msg/936506d83fea4458
 */
netscore.loadLibs = function() {
  google.load('visualization', '1', {'callback': netscore.visualizationLoaded,
    'packages': ['corechart', 'table']});
};


/**
 * The primary entry point for net-score.
 */
netscore.start = function() {
  //used for all tests to enable tracking via Google analytics.
  track.trackMe(track.trackingCode);

  //used only when we plan on running tests and want to record the user agent
  track.userAgent();

  //dynamically loaded JavaScript that can not be included at compile time
  netscore.loadLibs();

  //TODO(gavaletz) make this use events?
  //Assign the callbacks
  for (i in netscore.workList) {
    netscore.workList[i].nextFunction = netscore.doneNow;
  }

  //Logic here is that we only start the first function if test setup is done
  // and the maps API is loaded.
  netscore.workReady = true;
  try {
    netscore.workList[netscore.workIndex].start();
  }
  catch (err) {
    datastore.logError('netscoreError', 'workList[' + netscore.workIndex + ']');
    netscore.doneNow();
  }
};
//used by the closure compiler to eport this function call
goog.exportProperty(window, 'netscoreStart', netscore.start);


/**
 * Callback for each test to call when finished.
 *
 * This is assigned in netscore.start() to each item in the work list's
 * nextFunction.  When this is called we call the start method for the next item
 * in the work list or move on to do other things if the necessary dependencies
 * have been met.
 */
netscore.doneNow = function() {
  netscore.workIndex += 1;
  if (netscore.workIndex < netscore.workList.length) {
    try {
      netscore.workList[netscore.workIndex].start();
    }
    catch (err) {
      datastore.logError('netscoreError', 'workList[' + netscore.workIndex +
          ']');
      netscore.doneNow();
    }
  }
  else {
    netscore.workDone = true;
    datastore.postJson();
    if (netscore.visReady && datastore.resultKey != '') {
      netscore.displayResults();
    }
    else if (netscore.visReady) {
      datastore.nextFunction = netscore.displayResults;
    }
  }
};


/**
 * Callback function for loading the charts API JavaScript library.
 *
 * Sets the indicator variable letting other functions know that the charts API
 * is loaded and if the test results are complete we can start displaying the
 * results..
 */
netscore.visualizationLoaded = function() {
  netscore.visReady = true;
  if (netscore.workDone && datastore.resultKey != '') {
    netscore.displayResults();
  }
  else if (netscore.workDone) {
    datastore.nextFunction = netscore.displayResults;
  }
};


/**
 * Loops over all the items in the work list and displays their results if they
 * have them.
 */
netscore.displayResults = function() {
  page.resultsSetup();
  for (i in netscore.workList) {
    try {
      netscore.workList[i].results();
    }
    catch (err) {
      datastore.logError('netscoreError', 'workList[' + netscore.workIndex +
          ']');
    }
  }
};
